This chapter describes three sample Web pages created using VBScript with techniques introduced in Part II, "Mastering the VBScript Language" (Chapters 4 through 10). The examples include
Example 1: A credit-card number validation program for an online mail-order company
Example 2: A home page that's different every time you load it
Example 3: A links page that caters to both daytime and nighttime audiences
Document title: Credit Card Verification Form
Files:
Page file: cardver.html (see Figure 11.1)
Images:
Description: Mega Mail Order, the company you first met in Chapter 5 "Interfacing VBScript with an HTML Form," accepts credit-card payments over the Internet for its new wonder product-the LazeeGeek Computer Users Head Prop. However, like all companies that accept credit-card numbers, it gets its share of mischievous visitors who complete the form with fictitious credit-card details, knowing very well that the order cannot be processed and that they'll never receive the goods. It must be said that very few people set out to defraud; in fact, the vast majority of credit-card failures are due to simple mistakes by the users. However, it does waste time. Mega Mail Order's sales clerks call the authorization center only to be told that the transactions cannot be authorized.
The usual answer is to create or obtain a CGI script that validates the credit-card number. Using a simple algorithm, it is possible to determine whether a credit-card number is false or genuine. However, it is much quicker and more efficient to process the validation at the client machine rather than at the server.
The validation routines check the expiration date of the card and then perform a check on the card number to see whether it passes through the algorithm. There are actually three algorithms for 13-, 15-, and 16-digit cards.
Note |
The use of credit cards for payment on the Internet has been a controversial subject for many months. I have my own opinions, but I'm not writing a book on that! If you do plan to accept credit cards at your Web site, you should note a few important points. Only accept credit-card details through the Secure Sockets Layer (SSL). For this, you need a digital certificate from VeriSign, which can be obtained at http://www.verisign.com/. When you receive the credit-card details via SSL from the client, do not use a CGI script to e-mail the form details to your home or office location (assuming you use a remote server), unless you use an equally safe encryption method for transmitting the e-mail. You might be wondering how to obtain your order details. The safest method is to store the details on the server and send an e-mail to yourself alerting you that an order is ready to be collected from the server. Set up a password-secure form that you and you alone can log into (again, through SSL), and collect the details online. This type of server-side processing is beyond the scope of this book. If you plan to use this script on your Web site, remember that client-side scripts are currently visible via the View Source menu option. It wouldn't take long for an experienced programmer to learn how to change the script in order to get around your validation. Suppose the hacker saves a copy of the form to a local drive, amends it, gets back online, loads the hacked page from his hard drive, enters garbage in the form, and submits it. If you run a credit-card form like this on a normal server, there is nothing you can do; the now unvalidated data hits your server and causes all the same problems you had before. However, if you run the form from a secure server, the hacker gets stuck completely. The form must come from the secure server to establish the SSL connection. The hacker simply cannot create the SSL link without downloading the credit-card form from your server. The form's action parameter is set to an https:// location. Therefore, if data is sent to the server "in the clear," it will not be understood. This obviously is another good reason to accept credit cards only via an SSL connection. Finally, this script can only validate the fact that the number is a real credit-card number. You still need to obtain an authorization number from the credit-card company. |
Dates: (See Chapter 8 "Adding Date and Time Functions.") The script obtains the current month and year from the user's machine and compares this against the expiration date given by the card holder. The expiration date is first checked to ensure that it is a valid date (as far as the computer is concerned). The user can enter any valid combination of month and year, including Aug-97, 8/97, and August 97. The fact that this sort of validation using a server-side CGI script is a very complex program is another good reason to use client-side scripting and VBScript in particular.
Subroutines and functions: (See Chapter 9 "Making Your Program Flow.") The program consists of several functions and related subroutines, as well as event handlers.
String manipulation: (See Chapter 7 "Manipulating Strings.") The program has to remove any spaces, commas, dashes, or whatever the client used to delimit the series of numbers. You achieve this by looking at the problem in reverse; that is, you look for the numbers rather than the delimiters, so that it does not matter which delimiting character the user included within the card number. You use more string manipulation in the actual algorithm itself, which must split the overall credit-card number into individual numbers.
String conversion: (See Chapter 7.) After the numbers (which are actually string representations of numbers) are dissected, a calculation is performed on them, so they must be converted to integers.
Operators: (See Chapter 4 "Using the VBScript Language.") On several occasions, the script uses a range of comparison, logical, and arithmetic operators.
Loops and decisions: (See Chapter 9.) The program contains several If...Then and Select Case statements, as well as a nested Select Case block.
Arrays: (See Chapter 10, "Using the Power of Arrays.") One of the three algorithms uses a static, single-dimension array as temporary storage for the individual numbers of the credit-card number.
HTML intrinsic controls: (See Chapter 5.) The form uses only HTML controls; no ActiveX controls are used.
Figure 11.2 shows what happens when a user tries to enter the details of a credit card that has expired. Keep in mind, though, that this part of the validation works with the client machine's date variable, which is under the control of the user.
Figure 11.2 : cardver.html detecting an expired card.
Figure 11.3 shows that the algorithm has either sucessfully foiled a potential fraud or has alerted the user to a typing error.
Figure 11.3 : cardver.html detecting a credit-card fraudster-me!.
Until I stumbled across the algorithm that forms the basis of this credit-card verification program, it had never struck me that credit-card numbers are constructed in a particular way. They just seemed like a bunch of random numbers!
However, credit-card numbers are all put together in such a way that by applying an algorithm to them, you can very quickly identify a bogus number. No matter what type of card is being used, the numbering systems all work in a similar way, so here's how they work. First, multiply every other digit by two-that is (depending on the card type), digits 1, 3, 5, and so on, or 2, 4, 6, and so on. If the result of the multiplication is greater than 10, add the two digits. For example, let's say the second digit of a credit- card number is 6. If you multiply it by 2, that equals 12; if you add 1 and 2, that equals 3. When you've done this for every other number, add all the digits of the credit-card number. If the result is divisible by 10 (such as 50, 60, or 70), the number is genuine. If it does not divide by 10, the number is false. Here is an example:
Credit-card number: 4578-7895-1232-0051
With a 16-digit number, you multiply digits 1 through 15 by 2, and reduce them to single-digit results, as described in the preceding paragraph.
New number: 8558-5895-2262-0011
Now add all these digits together. The result is 67-a bogus number.
While porting this example to VBScript from Perl, I tested the algorithm on over 60 credit-card numbers that had been received on one of my clients' Web sites. Amazingly, the two that the algorithm rejected were also the two that had failed authorization-probably not that amazing when you think about it!
The complete listing for the credit-card verification example is shown in Listing 11.1.
Listing 11.1. The cardver.html code.
<HTML> <HEAD> <TITLE>Credit Card Number Verification</TITLE> <SCRIPT LANGUAGE="vbscript"> ' 'Create two variables with global scope ' Dim paymethod Dim TheCardType ' 'This is the main subroutine and is called by the button's 'onclick event handler ' Sub VerifyCard dim strCleanNo dim verified dim currdate 'check the date if bad then quit If Not GoodDate() Then Exit Sub End If 'take all spaces etc out of the string strCleanNo = CleanString() 'determine the type of card and send execution off in the right direction Select Case TheCardType Case "amex" verified = verifyAmex(strCleanNo) Case "visa" 'this is a nested select Select Case Len(strCleanNo) Case 13 verified = verifyV(strCleanNo) Case 16 verified = verifyMC(strCleanNo) Case Else verified = False End Select Case "mastercard" verified = verifyMC(strCleanNo) Case "discovery" verified = verifyMC(strCleanNo) Case Else Alert "Please select a Card Type" Exit Sub End Select 'is it ok or not? If Not verified Then i = MsgBox("INVALID CARD NUMBER",16,"Cannot Submit Data") Else i = MsgBox("The Card No. is OK",64,"Submitting Data....") End If End Sub ' 'This is the function that checks the date ' Function GoodDate() GoodDate = True If Not IsDate(Document.Form1.CardExp.Value) Then i = MsgBox("Invalid Expiry Date",16,"Cannot Submit Data") GoodDate = False Else currdate = Month(Now()) & " " & Year(Now()) If DateValue(Document.Form1.CardExp.Value) < DateValue(currdate) Then i = MsgBox("THIS CARD HAS EXPIRED",16,"Cannot Submit Data") GoodDate = False End If End If End Function ' 'This function validates an amex card ' Function VerifyAmex(ByVal CardNo) Dim amexarray(14) Dim tot tot=0 ' 'The first check - Amex Cards must be 15 digits If Len(CardNo) <> 15 Then VerifyAmex = False Exit Function End If ' 'Separate all digits in even numbered positions into 'an array - this will make the final addition easier For x = 2 to 10 step 2 amexarray(x-1) = Mid(CardNo,x,1) Next ' 'Now put the last four digits into the array too For x = 12 to 15 amexarray(x-1) = Mid(CardNo,x,1) Next ' 'Multiply all the numbers in odd numbered positions 'by two and reduce them to single digit answers For x = 1 to 11 Step 2 y = Mid(CardNo,x,1) * 2 If y >= 10 Then ' 'The Mod Function returns only the remainder of a division 'when the result is calculated put it too into the array amexarray(x-1) = (y Mod 10) + 1 Else amexarray(x-1) = y End If Next ' 'Finally add up all the numbers you've got stored in the array For x = 0 to 14 tot = tot + CInt(amexarray(x)) Next ' 'If the tot variable is divisible by 10 then Mod will return '0, that is no remainder If tot Mod 10 = 0 Then VerifyAmex = True Else VerifyAmex = False End If End Function ' 'This function checks visa 13 digit cards ' Function VerifyV(ByVal CardNo) Dim vArray(12) Dim tot tot=0 ' 'Move all the numbers in the even numbered positions 'into an array For x = 2 to 12 step 2 vArray(x-1) = Mid(CardNo,x,1) Next '..and the thirteenth number vArray(12) = Mid(CardNo,13,1) ' 'mulitply all the numbers in the odd numbered positions by 2 'and reduce to a single digit result For x = 1 to 11 Step 2 y = Mid(CardNo,x,1) * 2 If y >= 10 Then ' 'Mod returns the remainder of a division 'when you have a single digit result add that 'to the array also. vArray(x-1) = (y Mod 10) + 1 Else vArray(x-1) = y End If Next ' 'run through the whole array adding up the numbers 'as you go For x = 0 to 12 tot = tot + CInt(vArray(x)) Next ' 'check to see if the result is divisible by 10 If tot Mod 10 = 0 Then VerifyV = True Else VerifyV = False End If End Function ' 'Although it says MC it's actually a multi purpose 16 digit checker ' Function VerifyMC(ByVal CardNo) Dim tot tot=0 'first check, must be 16 digits If Len(CardNo) <> 16 Then VerifyMC = False Exit Function End If ' 'this one's slightly different, without using an array 'firstly add up all the numbers occupying even numbered 'positions For x = 2 to 16 step 2 tot = tot + CInt(Mid(CardNo,x,1)) Next ' 'all the numbers in odd numbered locations are multiplied 'by 2 and reduced to single digit results, then added to 'the running total For x = 1 to 15 Step 2 y = Mid(CardNo,x,1) * 2 If y >= 10 Then tot = tot + CInt((y Mod 10) + 1) Else tot = tot + CInt(y) End If Next ' 'again check that the result is divisible by 10 If tot Mod 10 = 0 Then VerifyMC = True Else VerifyMC = False End If End Function ' 'This function looks for numbers in the card number string, thereby 'removing all non numeric characters ' Function CleanString() dim strLen dim strCounter dim strClean dim strDirty ' 'copy the complete number as entered by the user in 'the srtDirty variable strDirty = Trim(Document.Form1.cardnumber.value) ' 'find its total length strLen = Len(strDirty) ' 'initalize the variable which will hold the final 'cleaned credit card number strClean = "" ' 'it's easier to check for numbers and reject everything else For strCounter = 1 to strLen If Asc(Mid(strDirty,strCounter,1)) < 58 AND Asc(Mid(strDirty,strCounter,1)) > 47 Then ' 'if this character is a number, concatenate it to the clean number thereby removing all dashes, spaces or whatever delimiter the user has included. strClean = strClean & Mid(strDirty,strCounter,1) End If Next ' 'return the final credit card number minus delimiters CleanString = strClean End Function 'et voila </SCRIPT> </HEAD> <BODY BACKGROUND="bground.jpg"> <FONT FACE="arial" SIZE=2> <CENTER> <TABLE> <TD><IMG SRC="visa.gif"> <TD><IMG SRC="master.gif"> <TD><IMG SRC="amex.gif"> </TABLE> <P> <BR><BR> <BLOCKQUOTE> If you are paying by credit card, please complete this section of the form. </BLOCKQUOTE> <FORM NAME="Form1"> <TABLE> <TD ALIGN=RIGHT><B>Visa</B> <TD> <!-- The event handlers attached to the following controls were added using the ActiveX Control Pad > <INPUT LANGUAGE="vbscript" TYPE=RADIO VALUE="visa" OncLICK="TheCardType= "visa"" NAME="cardtype"> <TD ALIGN=RIGHT><B>Mastercard</B> <TD><INPUT LANGUAGE="vbscript" TYPE=RADIO VALUE="mastercard" OncLICK="TheCardType= "mastercard"" NAME="cardtype"> <TR> <TD ALIGN=RIGHT><B>American Express</B> <TD><INPUT LANGUAGE="vbscript" TYPE=RADIO VALUE="amex" OncLICK="TheCardType= "amex"" NAME="cardtype"> <TD ALIGN=RIGHT><B>Discover</B> <TD><INPUT LANGUAGE="vbscript" TYPE=RADIO VALUE="discovery" OncLICK="TheCardType= "discovery"" NAME="cardtype"> <TR> </TABLE> <P> <TABLE> <TD><B>Cardholder's Name</B> <TD><INPUT TYPE=TEXT SIZE=30 NAME="cardholder"> <TR> <TD><B>Card Number</B> <TD><INPUT TYPE=TEXT SIZE=20 NAME="cardnumber"> <TR> <TD><B>Card Expiration Date</B> <TD><INPUT TYPE=TEXT SIZE=5 NAME="cardexp"> <TR> </TABLE> <P> <INPUT LANGUAGE="vbscript" TYPE=button VALUE="Check" OncLICK=" call VerifyCard()"> <INPUT TYPE=RESET VALUE="Clear/Reset"> </FORM> </BODY> </HTML>
Document title: Randolph Randal's Random Home Page
Files:
Page file: random.html (see Figures 11.4, 11.5, and 11.6)
Images:
Figure 11.5 : random.html--same page, same code, different look .
Figure 11.6 : random.html--again You get the picture? You can have same fun with this concept .
Description: To keep visitors interested, Randolph Randal randomized his home page. The page uses the simple random function built into VBScript to return a number between 0 and 4. Randolph then uses this number to select the background graphic for the page and also extract data from a prebuilt array of link colors, font colors, and so on.
Subroutines and functions: (See Chapter 9.) The program consists of two script blocks with no subroutines, so the scripts execute upon loading in the browser.
Arrays: (See Chapter 10.) The page uses a number of single-dimension static arrays to store the page style data.
Language elements: The page uses the Rnd() function and several other basic language elements. It also uses the Document.Write method, which was used in several examples in this Part. Chapter 18, "Interacting with the Browser," discusses Document.Write in more detail.
The complete listing for Randolph Randal's Random Home Page (random.html) is shown in Listing 11.2.
Listing 11.2. The random.html code.
<HTML> <TITLE>Randolph Randal's Random Home Page</TITLE> </HEAD> <SCRIPT LANGUAGE="vbscript"> 'create arrays for the body tag variables Dim Lnk(4) Dim VLnk(4) Dim FColor(4) Dim Fnt(4) 'create a global variable Dim x 'Variables for Version No. 1 Lnk(0) = "Fuchsia" Vlnk(0) = "Silver" FColor(0) = "Lime" Fnt(0) = "arial" 'Variables for Version No. 2 Lnk(1) = "blue" Vlnk(1) = "fushia" FColor(1) = "white" Fnt(1) = "times roman" 'Variables for Version No. 3 Lnk(2) = "green" Vlnk(2) = "maroon" FColor(2) = "blue" Fnt(2) = "arial" 'Variables for Version No. 4 Lnk(3) = "lime" Vlnk(3) = "teal" FColor(3) = "yellow" Fnt(3) = "ms sans serif" 'Variables for Version No. 5 Lnk(4) = "navy" Vlnk(4) = "gray" FColor(4) = "black" Fnt(4) = "arial" 'initialize the generator RANDOMIZE 'generate a random number twixt none and four x = Int((5 - 1 + 1) * Rnd) 'turn said number into a string making sure there are no spaces strX = Trim(CStr(x)) 'add the jpg file extension and you've got a file name randomimage = strX & ".jpg" 'write the randomly generated body tag into the document Document.Write "<BODY BACKGROUND=" & Chr(34) & randomimage & Chr(34) Document.Write " TEXT=" & FColor(x) Document.Write " LINK=" & Lnk(x) Document.Write " VLINK=" & Vlnk(x) Document.Write ">" Document.Write "<FONT FACE=" & Fnt(x) & " SIZE=3>" </SCRIPT> <CENTER> <H2>Wow...Different Again Huh?????</H2> <B> <A HREF="">CLICK THIS LINK</A> <P> <A HREF="">THIS IS ANOTHER LINK</A> <P> </B> <H2>I have a randomly changing Home Page.. see if you can collect the set!!</H2> <H3>This is version No. <!-- This writes the Version Number using the x global variable --> <SCRIPT LANGUAGE="vbscript"> Document.Write CStr(x+1) </SCRIPT> </H3> </CENTER> </FONT> </BODY> </HTML>
Document title: Tim Day's Link Page
Files: The page file is links.html (see Figures 11.7 and 11.8), and the images are day.jpg and stars.gif.
Figure 11.7 : links.html by day.
Figure 11.8 : links.html by night.
Description: Tim Day's link page uses the client machine's time variable to create a different look and different links for day and night users of the site.
Dates: (See Chapter 8.) The script obtains the hour from the user's machine and calculates whether it is day or night.
Subroutines and functions: (See Chapter 9.) The program consists of two script blocks with no subroutines, so the scripts execute upon loading in the browser.
Operators: (See Chapter 4.) On several occasions, the script uses a range of comparison, logical, and arithmetic operators.
Decisions: (See Chapter 9.) The program uses the If...Then conditional operator to determine day or night.
Arrays: (See Chapter 10.) The body tag variables use several single-dimensional static arrays. In addition, the link descriptions and link URLs use a pair of two-dimensional arrays.
The complete code for links.html is shown in Listing 11.3.
Listing 11.3. The links.html code.
<HTML> <TITLE>Tim Day's Link Page</TITLE> </HEAD> <SCRIPT LANGUAGE="vbscript"> 'create arrays for the body tag variables Dim Lnk(1) Dim VLnk(1) Dim FColor(1) Dim Fnt(1) Dim Greet(1) 'declare two dimensional arrays for the links Dim LinkDesc(1,4) Dim LinkURL(1,4) 'declare two constants Dim DAYTIME Dim NIGHTTIME DAYTIME = 1 NIGHTTIME = 0 'create a global variable Dim x 'Variables for Nighttime Version Lnk(NIGHTTIME) = "blue" Vlnk(NIGHTTIME) = "fushia" FColor(NIGHTTIME) = "yellow" Fnt(NIGHTTIME) = "times roman" Greet(NIGHTTIME) = "Take it easy tonight - <BR> visit some of my favorite sites" 'Variables for Daytime Version Lnk(DAYTIME) = "red" Vlnk(DAYTIME) = "teal" FColor(DAYTIME) = "orange" Fnt(DAYTIME) = "ms sans serif" Greet(DAYTIME) = "Here are some cool sites <BR>to help you through the day" 'Descriptions for the Links LinkDesc(NIGHTTIME,0) = "101 Cocktail Recipes" LinkDesc(NIGHTTIME,1) = "Cures for Insomnia" LinkDesc(NIGHTTIME,2) = "UFO Central" LinkDesc(NIGHTTIME,3) = "The Games Web Site" LinkDesc(NIGHTTIME,4) = "Ghost Stories on the Web" LinkDesc(DAYTIME,0) = "Net Supermarket" LinkDesc(DAYTIME,1) = "C|Net News" LinkDesc(DAYTIME,2) = "Microsoft" LinkDesc(DAYTIME,3) = "Computer Shopper" LinkDesc(DAYTIME,4) = "Sams.Net" 'URLs for the Links - these aren't real links ;-) LinkURL(NIGHTTIME,0) = "http://1" LinkURL(NIGHTTIME,1) = "http://2" LinkURL(NIGHTTIME,2) = "http://3" LinkURL(NIGHTTIME,3) = "http://4" LinkURL(NIGHTTIME,4) = "http://5" LinkURL(DAYTIME,0) = "http://1" LinkURL(DAYTIME,1) = "http://2" LinkURL(DAYTIME,2) = "http://3" LinkURL(DAYTIME,3) = "http://4" LinkURL(DAYTIME,4) = "http://5" 'Determine whether it's day or night TheHour = Hour(Now()) If TheHour >= 5 and TheHour < 20 Then x = DAYTIME theimage = "day.jpg" Else x = NIGHTTIME theimage = "stars.gif" End If 'write the body tag etc into the document Document.Write "<BODY BACKGROUND=" & Chr(34) & theimage & Chr(34) Document.Write " TEXT=" & FColor(x) Document.Write " LINK=" & Lnk(x) Document.Write " VLINK=" & Vlnk(x) Document.Write ">" Document.Write "<FONT FACE=" & Fnt(x) & " SIZE=3>" Document.Write "<CENTER>" Document.Write "<H2>" & Greet(x) & "</H2><P><B>" 'write the links For i = 0 to 4 Document.Write "<A HREF=" & Chr(34) & LinkURL(x,i) & Chr(34) & "><P>" Document.Write LinkDesc(x,i) Document.Write "</A>" Next </SCRIPT> </CENTER> </FONT> </BODY> </HTML>